docs(approvals): drop duplicate role-vs-position callout (unbreak role-word ratchet)#3122
Closed
os-zhuang wants to merge 1 commit into
Closed
docs(approvals): drop duplicate role-vs-position callout (unbreak role-word ratchet)#3122os-zhuang wants to merge 1 commit into
os-zhuang wants to merge 1 commit into
Conversation
…e-word ratchet) The ESLint job's "Reserved-word (role) docs ratchet" step has been red on main since 25a19be, which took approvals.mdx from 5 -> 9 role-word occurrences. Every open PR inherits the red check. The occurrences are NOT ADR-0090 D3 drift and cannot be reworded away: `role` is a real, shipping approver type (spec/src/automation/approval.zod.ts:14) that resolves against better-auth's org-membership tier (`sys_member.role`), which D3 names as its single documented exception ("third-party schema we do not own"). Writing `position` in these spots would make the docs wrong -- telling the two apart is the entire point of the passage, and of the `approval-role-not-membership-tier` lint rule. What the ratchet did catch is real redundancy: the new callout under "The request opens, the run pauses" restates the callout ~75 lines above it, which says the same thing and more (it names the lint rule). Removed the duplicate. That leaves `role:<r>` in the approverId filter list -- a genuine new fact at the same sanctioned boundary (spec/src/contracts/approval-service.ts:231). Rather than delete a true API detail to satisfy a counter, the surviving callout is tightened: it stated role-the-approver-type twice ("The `role` approver type ..." and "authored as `type: 'role'`"), now once. That frees the slot, so the file lands back at exactly 5. Baseline deliberately NOT bumped -- a high-water mark that only ratchets down is the point of the gate. Verified: node scripts/check-role-word.mjs -> OK (exit 0); pnpm lint -> exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Jul 17, 2026
Contributor
Author
xuyushun441-sys
pushed a commit
that referenced
this pull request
Jul 17, 2026
…l` (#3133) `ApproverType.role` was the last platform surface projecting the word ADR-0090 D3 reserved. Renaming it also unbreaks `lint.yml` on main: the role-word ratchet has been red since #3113 (approvals.mdx 5 → 9), and the docs stop needing the word once the type is spelled correctly. D3's exception does not cover this enum. It protects better-auth's own `sys_member.role` COLUMN — third-party schema we cannot rename. `ApproverType` is ours: an authoring surface, i.e. the *projection*, which D3 says is spelled `org_membership_level` and labelled "organization membership", never "role". The sentence licensing the leak is itself false. ADR-0090 D3:203 claims `sys_member.role` is "already relabelled `org_membership_level` in the platform projection (ADR-0057 D7)" — but `org_membership_level` appeared nowhere in the codebase (one comment in position.zod.ts), and ADR-0057 D7:335 lists that relabel under "Deferred (evidence-gated, P4)". The projection never landed, so the word reached authors. The name manufactured a silent failure ("hotcrm class"): every sibling surface renamed to `position` (`sys_role`, `ShareRecipientType.role`, `ctx.roles[]`), so `{ type: 'role', value: 'sales_manager' }` reads as a position's legacy spelling. It resolves against the membership tier, finds no member row, falls back to an inert `role:sales_manager` literal, and the request waits forever. Repo-wide, `type: 'role'` had ZERO real callers — only lint tests and the docs warning that exists to undo the confusion the name creates. - spec: `ApproverType` gains `org_membership_level`; `role` kept as a deprecated alias for one window so a published 15.x flow keeps loading. `DEPRECATED_APPROVER_TYPES` + `canonicalApproverType()` are the single source for the mapping (runtime and lint both read it). - plugin-approvals: resolves on the canonical type, warns on the deprecated spelling, `expandRoleUsers` → `expandMembershipTierUsers`. The `type:value` fallback literal deliberately keeps the AUTHORED spelling — 15.x wrote `role:<v>` into `sys_approval_approver` / `pending_approvers`, and canonicalising it here would orphan every stored slot. - lint: `approval-role-not-membership-tier` → `approval-approver-not-membership-tier` (the rule id carried the word too), plus `approval-approver-type-deprecated`. Mutually exclusive: a bad VALUE wins, because prescribing `org_membership_level` for a position name is wrong advice — the fix there is `position`. - docs/skill/reference + role-word baseline ratcheted DOWN (approvals.mdx 5 → 1, automation SKILL.md 3 → 1); api-surface snapshot regenerated (0 breaking, 2 added). Studio still offers "Role" and its picker calls `client.list('role')` on a metadata type D3 deleted — that picker is already dead, and the dropdown is objectui's own hardcoded copy of this enum. Tracked as objectui follow-up in degrades to free text (strictly better than a picker that lists nothing). Closes #3133. Supersedes #3120 and #3122, which only deleted the duplicated docs callout without touching the name that causes the confusion. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
xuyushun441-sys
pushed a commit
that referenced
this pull request
Jul 17, 2026
…l` (#3133) `ApproverType.role` was the last platform surface projecting the word ADR-0090 D3 reserved. Renaming it also unbreaks `lint.yml` on main: the role-word ratchet has been red since #3113 (approvals.mdx 5 → 9), and the docs stop needing the word once the type is spelled correctly. D3's exception does not cover this enum. It protects better-auth's own `sys_member.role` COLUMN — third-party schema we cannot rename. `ApproverType` is ours: an authoring surface, i.e. the *projection*, which D3 says is spelled `org_membership_level` and labelled "organization membership", never "role". The sentence licensing the leak is itself false. ADR-0090 D3:203 claims `sys_member.role` is "already relabelled `org_membership_level` in the platform projection (ADR-0057 D7)" — but `org_membership_level` appeared nowhere in the codebase (one comment in position.zod.ts), and ADR-0057 D7:335 lists that relabel under "Deferred (evidence-gated, P4)". The projection never landed, so the word reached authors. The name manufactured a silent failure ("hotcrm class"): every sibling surface renamed to `position` (`sys_role`, `ShareRecipientType.role`, `ctx.roles[]`), so `{ type: 'role', value: 'sales_manager' }` reads as a position's legacy spelling. It resolves against the membership tier, finds no member row, falls back to an inert `role:sales_manager` literal, and the request waits forever. Repo-wide, `type: 'role'` had ZERO real callers — only lint tests and the docs warning that exists to undo the confusion the name creates. - spec: `ApproverType` gains `org_membership_level`; `role` kept as a deprecated alias for one window so a published 15.x flow keeps loading. `DEPRECATED_APPROVER_TYPES` + `canonicalApproverType()` are the single source for the mapping (runtime and lint both read it). - plugin-approvals: resolves on the canonical type, warns on the deprecated spelling, `expandRoleUsers` → `expandMembershipTierUsers`. The `type:value` fallback literal deliberately keeps the AUTHORED spelling — 15.x wrote `role:<v>` into `sys_approval_approver` / `pending_approvers`, and canonicalising it here would orphan every stored slot. - lint: `approval-role-not-membership-tier` → `approval-approver-not-membership-tier` (the rule id carried the word too), plus `approval-approver-type-deprecated`. Mutually exclusive: a bad VALUE wins, because prescribing `org_membership_level` for a position name is wrong advice — the fix there is `position`. - docs/skill/reference + role-word baseline ratcheted DOWN (approvals.mdx 5 → 1, automation SKILL.md 3 → 1); api-surface snapshot regenerated (0 breaking, 2 added). Studio still offers "Role" and its picker calls `client.list('role')` on a metadata type D3 deleted — that picker is already dead, and the dropdown is objectui's own hardcoded copy of this enum. Tracked as objectui follow-up in degrades to free text (strictly better than a picker that lists nothing). Closes #3133. Supersedes #3120 and #3122, which only deleted the duplicated docs callout without touching the name that causes the confusion. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 17, 2026
…l` (#3137) Closes #3133. Renames the last platform surface projecting the ADR-0090 D3 reserved word: `ApproverType.role` → `org_membership_level`, with `role` kept as a deprecated alias for one window (resolves identically, warns). Publishes `xEnumDeprecated` on the node configSchema so Studio drops the deprecated spelling from the approver-type picker. Supersedes #3120/#3122. objectui half: objectstack-ai/objectui#2643 (merged). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why main is red
The
ESLintjob of Lint & Type Check fails onmainat its Reserved-word ("role") docs ratchet step, so every open PR inherits a red check.pnpm lintitself is clean — this is not an eslint rule failure.Introduced by 25a19be (#3113). Red at 021ba4c and every commit after.
The occurrences are not drift — and must not be reworded
The obvious fix (swap
role→ the D3 vocabulary) is wrong here, so this PR does not do it:roleis a real, shipping approver type —approval.zod.ts:14, sitting in the enum next topositionwith a comment explaining exactly why it stays.sys_member.role: owner/admin/member) — which ADR-0090 D3 names as its single documented exception: "the better-auth boundary —sys_member.roleis third-party schema we do not own; it remains."positionin these spots would make the docs factually wrong. Distinguishing the two is the entire point of the passage — and of theapproval-role-not-membership-tierlint rule, which exists precisely because authors confuse them and their approvals silently route to nobody.What the ratchet did catch
Real redundancy. The callout added under "The request opens, the run pauses" restates the callout ~75 lines above it — same fact, same page, and the older one says more (it names the lint rule and
sys_user_position). Removed the duplicate (−3 occurrences). That's a docs improvement on its own merits.That left
role:<r>in theapproverIdfilter list (−1 short): a genuine new fact at the same sanctioned boundary (approval-service.ts:231). Rather than delete a true API detail to satisfy a counter, the surviving callout is tightened — it stated role-the-approver-type twice ("Theroleapprover type is…" and "authored astype: 'role'"), now once. That frees the slot and the file lands back at exactly 5.Baseline deliberately NOT bumped
A high-water mark that only ratchets down is the point of the gate.
scripts/role-word-baseline.jsonis untouched — the only changed file is the.mdx.Reviewer's judgment call
I tightened the surviving callout partly to stay under the cap. If maintainers would rather keep that callout's original wording and ratchet the baseline 5 → 6 for
role:<r>, that is a defensible call — the ratchet is a blunt per-file counter that can't tell a sanctioned better-auth mention from real drift. I didn't make that call unilaterally, because it's a human decision, not a reflex.Verification
node scripts/check-role-word.mjsOK (49 baselined file(s), no new occurrences)— exit 0pnpm lintDocs-only change →
skip-changeset.🤖 Generated with Claude Code